<?php
/*微信支付*/
class WeiXinPay{
	private $appid;
	private $mch_id;
	private $key;
	private $notify_url;
	/**
	 * @param string $appid			微信分配的公众账号ID（企业号corpid即为此appId）
	 * @param string $mch_id		微信支付分配的商户号
	 * @param string $key			微信支付分配的密钥
	 * @param string $notify_url	接收微信支付异步通知回调地址
	 */
	public function __construct( $appid, $mch_id, $key, $notify_url){
		$this->appid		= $appid;
		$this->mch_id		= $mch_id;
		$this->key			= $key;
		$this->notify_url	= $notify_url;
	}
	/*统一下单接口*/
	public function unifiedorder($data){
		$arr['body']				= $data['body'];/*必须->商品描述*/
		$arr['out_trade_no']		= $data['out_trade_no'];/*必须->订单号*/
		$arr['total_fee']			= $data['total_fee'];/*必须->总金额*/
		$arr['trade_type']			= $data['trade_type'];/*必须->公众号支付JSAPI; 扫描支付NATIVE*/
		$arr['time_start']			= isset($data['time_start'])?$data['time_start']:'';//格式为20160331142901》》》date('YmdHis')
		$arr['time_expire']			= isset($data['time_expire'])?$data['time_expire']:'';//最短时间为5分钟
		$arr['openid']				= isset($data['openid'])?$data['openid']:'';/*非必须->用户openid (trade_type=JSAPI，此参数必传)*/
		$arr['product_id']			= isset($data['product_id'])?$data['product_id']:'';/*非必须->商品id trade_type=NATIVE*/
		$arr['attach']				= 'WeiXinPay';/*非必须->附加数据*/
		$arr['device_info']			= 'WEB';/*非必须->终端设备号 PC网页或公众号内支付请传"WEB"*/
		$arr['spbill_create_ip']	= getIp();/*必须->用户IP*/
		$arr['appid']				= $this->appid;/*必须->公众号id*/
		$arr['mch_id']				= $this->mch_id;/*必须->微信商户id*/
		$arr['notify_url']			= $this->notify_url;/*必须->接收微信支付异步通知回调地址*/
		$arr['nonce_str']			= $this->nonce_str();/*必须->随机字符串*/
		$arr['sign']				= $this->sign($arr);/*必须->签名*/
		$post						= $this->xml($arr);/*数组转XML*/
		$curl = curl_init();
		curl_setopt ( $curl, CURLOPT_URL, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
		curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt ( $curl, CURLOPT_POST, TRUE );
		curl_setopt ( $curl, CURLOPT_POSTFIELDS, $post );
		$result = curl_exec($curl);
		if(curl_errno($curl)!=0){
			echo curl_errno($curl).'<br/>'.curl_error($curl);exit;
		}
		curl_close($curl);
		return (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
	}
	/*
	*微信回掉地址方法
	*接收微信返回的xml，并记录到log之中
	*对xml进行签名验证，防止数据泄漏导致出现“假通知”，造成资金损失
	*签名验证通过之后返回数组数据
	 */
	public function notify(){
		$xml = file_get_contents('php://input');
		
		$data = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
		$trade_type = isset($data['trade_type'])?$data['trade_type']:'';

		$log = fopen('wxpay_notify.txt', 'a+');
		fwrite($log, ">>>>>>\n【接收到的notify通知】\n".$trade_type."\n".date('Y-m-d H:i:s')."\n".$xml."\n\n");

		$sign = isset($data['sign'])?$data['sign']:'';
		unset($data['sign']);
		$sign_our = $this->sign($data);
		if ($sign != $sign_our ) {
			fwrite($log, "签名错误$sign\t\n\n");
			return false;
		}
		fwrite($log, "签名正确\n\n");
		fclose($log);
		return $data;
	}
	/**
	*查询订单
	*transaction_id 微信订单id
	*out_trade_no	自己的订单id,当没提供transaction_id时需要传这个。
	*
	*				二者选其一，微信会优先使用微信订单id进行查询;
	**/
	public function orderQuery($arr){
		$arr['transaction_id']	= isset($arr['transaction_id'])?$arr['transaction_id']:'';
		$arr['out_trade_no']	= isset($arr['out_trade_no'])?$arr['out_trade_no']:'';
		$arr['appid']			= $this->appid;
		$arr['mch_id']			= $this->mch_id;
		$arr['nonce_str']		= $this->nonce_str();
		$arr['sign']			= $this->sign($arr);
		$post					= $this->xml($arr);/*数组转XML*/
		$curl = curl_init();
		curl_setopt ( $curl, CURLOPT_URL, 'https://api.mch.weixin.qq.com/pay/orderquery');
		curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt ( $curl, CURLOPT_POST, TRUE );
		curl_setopt ( $curl, CURLOPT_POSTFIELDS, $post );
		$result = curl_exec($curl);
		if(curl_errno($curl)!=0){
			echo curl_errno($curl).'<br/>'.curl_error($curl);exit;
		}
		curl_close($curl);
		$log = fopen('wxpay_notify.txt', 'a+');
		$data = (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
		if ('SUCCESS'===$data['return_code'] && 'SUCCESS'===$data['result_code']) {
			$trade_state = $data['trade_state'];
			$this->returnSuccessToWX();
		}
		fwrite($log, "【根据订单号查询结果】".date('Y-m-d H:i:s')."\n微信订单号：".$arr['transaction_id']."\t商户订单号：".$arr['out_trade_no']."\n".$result."\n\n【".$trade_state."】\n\n\n\n<<<<<<");
		fclose($log);
		return $data;
	}
	public function returnSuccessToWX(){
		echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
	}
	/*获取随机数*/
	public function nonce_str(){
		return md5(sha1(microtime(true).'the.white.rave'.mt_rand(0,99999)));
	}
	/*获取签名*/
	public function sign($arr){
		ksort($arr);
		$str = '';
		foreach ($arr as $key => $value) {
			if ($value) {
				$str .= $key.'='.$value.'&';
			}
		}
		return strtoUpper(MD5($str.'key='.$this->key));
	}
	/*获取xml*/
	private function xml($arr){
		$xml = "<xml>";
		foreach ($arr as $key=>$val){
		 if (is_numeric($val)) {
		 	$xml .= "<".$key.">".$val."</".$key.">";

		 } else
		 	$xml .= "<".$key."><![CDATA[".$val."]]></".$key.">";
		}
		$xml .= "</xml>";
		return $xml;
	}
}